import 'dart:async';
import 'package:flame/components.dart' hide Timer;
import 'package:flame/effects.dart';
import 'package:flame/flame.dart';
import 'package:flame/sprite.dart';
import 'package:flutter/material.dart';
import 'package:freedom/page/mahjong/event/disk_direction_update.dart';
import 'package:freedom/page/mahjong/keneck/dice_component.dart';
import 'package:freedom/page/mahjong/mahjong_game.dart';
import 'package:freedom/page/mahjong/util/user_location.dart';
import 'mahjong_context.dart';

class DiskDirection extends PositionComponent
    with HasGameRef<MahjongIndexGame> {
  Direction? current;
  int _currentOpacity = 30;

  double _speed = 200;

  int reckon = 30;

  Direction _bankerDirection = Direction.TOP;
  String _topStr = "", _rightStr = "", _leftStr = "", _bottomStr = "";

  final double _diskHeight = MahjongContext().centerDiskHeight;

  final List<String> dirStrList = ["东", "南", "西", "北"];

  //中间的 灰色块
  String src = 'mahjong/util/number.png';
  SpriteSheet? numberSheet;

  String getDirection(Direction source) {
    // 庄家下标 1  4
    int bankIndex = LocationUtil.FOUR_USER_LOCATION.indexOf(_bankerDirection);
    if (source == _bankerDirection) {
      return dirStrList[0];
    }
    return dirStrList[LocationUtil.getRange(bankIndex, source)];
  }

  DiskDirection({this.current})
      : super(
            size: Vector2(MahjongContext().centerDiskHeight,
                MahjongContext().centerDiskHeight),
            position: MahjongContext().diskDirectionPoint);

  @override
  FutureOr<void> onLoad() async {
    startTimer();
    //定位庄家位置
    _bankerDirection = MahjongContext.getUserDirection(
        MahjongContext().getBanker()?.userId ?? 0);
    // 定位闲家位置
    _topStr = getDirection(Direction.TOP);
    _rightStr = getDirection(Direction.RIGHT);
    _leftStr = getDirection(Direction.LEFT);
    _bottomStr = getDirection(Direction.BOTTOM);
    current = _bankerDirection;
    var numberImage = Flame.images.fromCache(src);
    numberSheet = SpriteSheet.fromColumnsAndRows(
      image: numberImage,
      columns: 10,
      rows: 1,
    );
    MahjongContext.registerRoomFunc<DiskDirectionUpdate>((event) {
      current = event.direction;
      reckon = 30;
    });
  }

  void startTimer() {
    Timer.periodic(const Duration(seconds: 1), (timer) {
      if (reckon > 0) {
        reckon--;
        if (reckon == 0) {
          reckon = 30;
        }
      }
    });
  }

  @override
  void render(Canvas canvas) {
    var paint = Paint()
      ..shader = const LinearGradient(
        colors: [Color(0xFF4B4B4B), Color(0xFF4B4B4B)], // 渐变色列表
        begin: Alignment.topRight, // 渐变起点
        end: Alignment.bottomLeft, // 渐变终点
      ).createShader(Rect.fromLTWH(
          size.x / 2 - MahjongContext().centerDiskHeight,
          MahjongContext().gameCenterY,
          MahjongContext().centerDiskHeight,
          MahjongContext().centerDiskHeight)); // 渐变范围
    //中间区域的半径
    double diskHeight = MahjongContext().centerDiskHeight;
    RRect outRRect = RRect.fromLTRBR(
        0, 0, diskHeight, diskHeight, Radius.circular(diskHeight / 6));
    canvas.clipRRect(outRRect);
    canvas.drawRRect(outRRect, paint);

    double outStrokeWidth = this.size.x / 10;

    Paint topBorderPaint = Paint()
      ..color = Color(0xff918832)
      ..style = PaintingStyle.stroke
      ..strokeWidth = outStrokeWidth;

    Paint rightBorderPaint = Paint()
      ..color = Colors.green
      ..style = PaintingStyle.stroke
      ..strokeWidth = outStrokeWidth;

    Paint bottomBorderPaint = Paint()
      ..color = Colors.blue
      ..style = PaintingStyle.stroke
      ..strokeWidth = outStrokeWidth;

    Paint leftBorderPaint = Paint()
      ..color = Color(0XEC8FFFFA)
      ..style = PaintingStyle.stroke
      ..strokeWidth = outStrokeWidth;

    canvas.drawLine(Offset(0, 0), Offset(size.x, 0), topBorderPaint);
    canvas.drawLine(
        Offset(size.x, 0), Offset(size.x, size.x), rightBorderPaint);
    canvas.drawLine(
        Offset(0, size.y), Offset(size.x, size.x), bottomBorderPaint);
    canvas.drawLine(Offset(0, 0), Offset(0, size.y), leftBorderPaint);

    // 绘制4个菱形
    Paint tPaint = Paint()
      ..color = Colors.black12 //Color(0x7E3F3F3F)
      ..strokeWidth = diskHeight / 40
      ..style = PaintingStyle.stroke;
    if (current != null && current == Direction.TOP) {
      tPaint
        ..color = Color.fromARGB(_currentOpacity, 145, 136, 50)
        ..style = PaintingStyle.fill;
    }

    RRect inRRect = RRect.fromLTRBR(diskHeight * 2 / 3, diskHeight * 2 / 3,
        diskHeight / 3, diskHeight / 3, Radius.circular(2.0));
    canvas.drawRRect(inRRect, Paint()..color = Color(0xAE8D8D8D));
    drawCountdown(canvas);
    Path tPath = Path();
    tPath.moveTo(0, 0);
    tPath.lineTo(diskHeight / 2 - diskHeight * 1 / 3 / 2, diskHeight / 3);
    tPath.lineTo(diskHeight / 2 + diskHeight * 1 / 3 / 2, diskHeight / 3);
    tPath.lineTo(diskHeight, 0);
    tPath.lineTo(0, 0);
    tPath.close();
    canvas.drawPath(tPath, tPaint);
    Paint lPaint = Paint()
      ..color = Colors.black12 //Color(0x7E3F3F3F)
      ..strokeWidth = diskHeight / 40
      ..style = PaintingStyle.stroke;
    if (current != null && current == Direction.LEFT) {
      lPaint
        ..color = Color.fromARGB(_currentOpacity, 143, 255, 250)
        ..style = PaintingStyle.fill;
    }
    Path lPath = Path();
    lPath.moveTo(0, 0);
    lPath.lineTo(diskHeight / 2 - diskHeight * 1 / 3 / 2, diskHeight / 3);
    lPath.lineTo(diskHeight / 2 - diskHeight * 1 / 3 / 2, diskHeight * 2 / 3);
    lPath.lineTo(0, diskHeight);
    lPath.lineTo(0, 0);
    lPath.close();
    canvas.drawPath(lPath, lPaint);

    Paint bPaint = Paint()
      ..color = Colors.black12 //Color(0x7E3F3F3F)
      ..strokeWidth = diskHeight / 40
      ..style = PaintingStyle.stroke;

    if (current != null && current == Direction.BOTTOM) {
      bPaint
        ..color = Color.fromARGB(_currentOpacity, 33, 150, 243)
        ..style = PaintingStyle.fill;
    }
    Path bPath = Path();
    bPath.moveTo(0, diskHeight);
    bPath.lineTo(diskHeight / 2 - diskHeight * 1 / 3 / 2, diskHeight * 2 / 3);
    bPath.lineTo(diskHeight / 2 + diskHeight * 1 / 3 / 2, diskHeight * 2 / 3);
    bPath.lineTo(diskHeight, diskHeight);
    bPath.lineTo(0, diskHeight);
    bPath.close();
    canvas.drawPath(bPath, bPaint);

    Paint rPaint = Paint()
      ..color = Colors.black12 //Color(0x7E3F3F3F)
      ..strokeWidth = diskHeight / 40
      ..style = PaintingStyle.stroke;
    if (current != null && current == Direction.RIGHT) {
      rPaint
        ..color = Color.fromARGB(_currentOpacity, 76, 175, 80)
        ..style = PaintingStyle.fill;
    }
    Path rPath = Path();
    rPath.moveTo(diskHeight, diskHeight);
    rPath.lineTo(diskHeight / 2 + diskHeight * 1 / 3 / 2, diskHeight * 2 / 3);
    rPath.lineTo(diskHeight / 2 + diskHeight * 1 / 3 / 2, diskHeight * 1 / 3);
    rPath.lineTo(diskHeight, 0);
    rPath.lineTo(diskHeight, diskHeight);
    rPath.close();
    canvas.drawPath(rPath, rPaint);

    double fontSize = diskHeight * 1 / 5;
    var tTextStyle = TextStyle(
        color: Color(0xff918832),
        fontSize: fontSize,
        fontWeight: FontWeight.w900);
    var tTextSpan = TextSpan(text: _topStr, style: tTextStyle);
    var tTextPainter = TextPainter(
      text: tTextSpan,
      textDirection: TextDirection.rtl,
    );
    tTextPainter.layout();
    tTextPainter.paint(
        canvas,
        Offset(
            size.x / 2 - tTextPainter.width / 2,
            outStrokeWidth +
                (size.y / 3 - outStrokeWidth - tTextPainter.height) / 2));

    var lTextStyle = TextStyle(
        color: Color(0XEC8FFFFA),
        fontSize: fontSize,
        fontWeight: FontWeight.w900);
    var lTextSpan = TextSpan(text: _leftStr, style: lTextStyle);
    var lTextPainter = TextPainter(
      text: lTextSpan,
      textDirection: TextDirection.rtl,
    );
    lTextPainter.layout();
    lTextPainter.paint(
        canvas,
        Offset(
            outStrokeWidth +
                (size.x / 3 - outStrokeWidth - lTextPainter.width) / 2,
            (size.y - lTextPainter.height) / 2));

    var rTextStyle = TextStyle(
        color: Colors.green, fontSize: fontSize, fontWeight: FontWeight.w900);
    var rTextSpan = TextSpan(text: _rightStr, style: rTextStyle);
    var rTextPainter = TextPainter(
      text: rTextSpan,
      textDirection: TextDirection.rtl,
    );
    rTextPainter.layout();
    //(size.x / 3 / 2 - lTextPainter.width / 2) / 2 + outStrokeWidth / 2,
    rTextPainter.paint(
        canvas,
        Offset(
            size.x * 2 / 3 +
                (size.x / 3 - outStrokeWidth - lTextPainter.width) / 2,
            (size.y - rTextPainter.height) / 2));

    var bTextStyle = TextStyle(
        color: Colors.blue, fontSize: fontSize, fontWeight: FontWeight.w900);
    var bTextSpan = TextSpan(text: _bottomStr, style: bTextStyle);
    var bTextPainter = TextPainter(
      text: bTextSpan,
      textDirection: TextDirection.rtl,
    );
    bTextPainter.layout();
    bTextPainter.paint(
        canvas,
        Offset(
            size.x / 2 - bTextPainter.width / 2,
            size.y * 2 / 3 +
                (size.y / 3 - outStrokeWidth - bTextPainter.height) / 2));
  }

  @override
  void update(double dt) {
    super.update(dt);
    _currentOpacity += (dt * _speed).toInt();
    if (_currentOpacity > 180) {
      _speed = -_speed.abs();
    } else if (_currentOpacity <= 20) {
      _speed = _speed.abs();
    }
  }

  // 添加两个筛子
  void addDice(int oneStopIndex, int twoStopIndex, List<int>? swapCard,
      {Function? success}) {
    Vector2 diceSize = Vector2.all(size.x / 3);
    Vector2 oneEnd = size - diceSize;
    Path onePath = Path()..quadraticBezierTo(size.x, 0, oneEnd.x, oneEnd.y);
    final Effect effect = MoveAlongPathEffect(
      onePath,
      EffectController(duration: 1),
    );
    DiceComponent one = DiceComponent(
        diceSize: diceSize,
        dicePosition: Vector2.all(0),
        stopIndex: oneStopIndex);
    one.add(effect);
    add(one);

    Vector2 twoEnd = Vector2.all(size.x / 3);
    Path twoPath = Path()
      ..quadraticBezierTo(-size.x, 0, twoEnd.x - size.x, diceSize.y - size.y);
    DiceComponent two = DiceComponent(
        diceSize: diceSize, dicePosition: size, stopIndex: twoStopIndex);
    final Effect twoEffect = MoveAlongPathEffect(
        twoPath,
        EffectController(
          duration: 1,
        ));
    two.add(twoEffect);

    add(TimerComponent(
        period: 1,
        onTick: () {
          // 开始交换动画
          gameRef.swapCardAction
              ?.startSwap(oneStopIndex + twoStopIndex, swapCard, () {
            one.removeFromParent();
            two.removeFromParent();
            if (success != null) {
              success();
            }
          });
        }));
    add(two);
  }

  // 添加中间的倒计时
  void drawCountdown(Canvas canvas) {
    int first, two;
    if (reckon < 10) {
      first = 0;
      two = reckon;
    } else {
      first = int.parse(reckon.toString().split("")[0]);
      two = int.parse(reckon.toString().split("")[1]);
    }
    Sprite sprite = numberSheet!.getSpriteById(first);
    Sprite sprite2 = numberSheet!.getSpriteById(two);
    sprite.render(canvas,
        position: Vector2(_diskHeight / 3,
            _diskHeight / 3 + (_diskHeight / 3 - _diskHeight / 6) / 2),
        size: Vector2(_diskHeight / 6, _diskHeight / 6));

    sprite2.render(canvas,
        position: Vector2(_diskHeight * 2 / 3 - _diskHeight / 6,
            _diskHeight / 3 + (_diskHeight / 3 - _diskHeight / 6) / 2),
        size: Vector2(_diskHeight / 6, _diskHeight / 6));
  }
}
